/* 
 * File:   SpriteManager.cpp
 * Copyright (C) 2009
 *		Sergio Padrino Recio (PadrinatoR)
 *
 * Created on 13 de diciembre de 2009, 17:46
 *
 * This file is part of BombProject.
 * 
 * BombProject is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
   
 * BombProject is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with BombProject.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "SpriteManager.h"

/**
 * Singleton instance.
 */
SpriteManager* SpriteManager::mInstance = NULL;

/**
 * Constructor.
 */
SpriteManager::SpriteManager()
{
	mResourceManager = ResourceManager::getInstance();
}

/**
 * Destructor.
 */
SpriteManager::~SpriteManager()
{

}

/**
 * Returns the singleton instance.
 * @return Returns the singleton instance.
 */
SpriteManager* SpriteManager::getInstance()
{
	if(mInstance == NULL);
		mInstance = new SpriteManager();

	return mInstance;
}

/**
 * Deletes the singleton instance.
 */
void SpriteManager::deleteInstance()
{
	if(mInstance == NULL) return;

	delete mInstance;
	mInstance = NULL;
}

/**
 * Creates a Player sprite as a foreground animated sprite based on the
 * specified character.
 * @param character Name of the character to be used.
 * @return Returns a pointer to the created Player.
 */
Player* SpriteManager::createPlayer(string character)
{
	Player* player = new Player();

	//TODO: set up the player: walking up/down/left/right
	player->addAnimation("walking_up", string("Chars/") + character + string("/walking_up.txt"));
	player->addAnimation("walking_down", string("Chars/") + character + string("/walking_down.txt"));
	player->addAnimation("walking_left", string("Chars/") + character + string("/walking_left.txt"));
	player->addAnimation("walking_right", string("Chars/") + character + string("/walking_right.txt"));

	addForegroundSprite(player);

	return player;
}

/**
 * Adds a background sprite.
 * @param sprite Sprite to be added.
 */
void SpriteManager::addBackgroundSprite(Sprite* sprite)
{
	mBackgroundSprites.push_back(sprite);
}

/**
 * Adds a foreground sprite.
 * @param sprite Sprite to be added.
 */
void SpriteManager::addForegroundSprite(Sprite* sprite)
{
	//TODO: add the new sprite so the new list remains sorted
	mForegroundSprites.push_back(sprite);
}

/**
 * Removes a foreground sprite.
 * @param sprite Sprite to be removed.
 */
void SpriteManager::removeForegroundSprite(Sprite* sprite)
{
	for(vector<Sprite*>::iterator i = mForegroundSprites.begin(); i != mForegroundSprites.end(); i++)
	{
		if((Sprite*) *i == sprite)
		{
			mForegroundSprites.erase(i);
			return;
		}
	}
}

/**
 * Removes a background sprite.
 * @param sprite Sprite to be removed.
 */
void SpriteManager::removeBackgroundSprite(Sprite* sprite)
{
	for(vector<Sprite*>::iterator i = mBackgroundSprites.begin(); i != mBackgroundSprites.end(); i++)
	{
		if((Sprite*) *i == sprite)
		{
			mBackgroundSprites.erase(i);
			return;
		}
	}
}

/**
 * Draws every registered sprite into the specified surface.
 * @param surface Target surface.
 */
void SpriteManager::drawAll(SDL_Surface* surface)
{
	for(Uint16 i = 0; i < mBackgroundSprites.size(); i++)
	{
		try
		{
			((AnimatedSprite*) (mBackgroundSprites[i]))->updateAnimation();
		}catch(...){}

		mBackgroundSprites[i]->draw(surface);
	}

	sortForegroundSprites();

	for(Uint16 i = 0; i < mForegroundSprites.size(); i++)
	{
		try
		{
			((AnimatedSprite*) (mForegroundSprites[i]))->updateAnimation();
		}catch(...){}

		mForegroundSprites[i]->draw(surface);
	}
}

/**
 * Sorts foreground sprites in growing Z. It uses <b>bubble sort</b>.
 */
void SpriteManager::sortForegroundSprites()
{
	Sprite* temp = NULL;
	bool sorted = true;

	//TODO: Test it and change it to QuickSort method
	for(Uint16 i = 0; i < mForegroundSprites.size(); i++)
	{
		sorted = true;

		for(Uint16 j = 0; j < mForegroundSprites.size() - i - 1; j++)
		{
			if(mForegroundSprites[j]->getZ() > mForegroundSprites[j+1]->getZ())
			{
				temp = mForegroundSprites[j];
				mForegroundSprites[j] = mForegroundSprites[j+1];
				mForegroundSprites[j+1] = temp;

				sorted = false;
			}
		}

		if(sorted) break;
	}
}
